"""
文件文档存储实现
支持原始文档的存储和检索
"""

import asyncio
import json
import uuid
from typing import List, Dict, Any, Optional
from pathlib import Path
from datetime import datetime

from ...core.interfaces import DocumentStoreInterface, Document
from ...core.events import EventEmitter


class FileDocumentStore(DocumentStoreInterface, EventEmitter):
    """基于文件系统的文档存储实现"""
    
    def __init__(self, storage_path: str = "./data/documents"):
        super().__init__()
        self.storage_path = Path(storage_path)
        self.metadata_file = self.storage_path / "metadata.json"
        self.documents_metadata = {}
        
    async def initialize(self):
        """初始化文档存储"""
        try:
            # 创建存储目录
            self.storage_path.mkdir(parents=True, exist_ok=True)
            
            # 加载元数据
            await self._load_metadata()
            
            await self.emit("document_store_initialized", {
                "storage_path": str(self.storage_path),
                "document_count": len(self.documents_metadata)
            })
            
        except Exception as e:
            await self.emit_error("document_store_initialization", e)
            raise
    
    async def _load_metadata(self):
        """加载文档元数据"""
        if self.metadata_file.exists():
            try:
                with open(self.metadata_file, 'r', encoding='utf-8') as f:
                    self.documents_metadata = json.load(f)
            except Exception as e:
                print(f"Warning: Failed to load metadata: {e}")
                self.documents_metadata = {}
        else:
            self.documents_metadata = {}
    
    async def _save_metadata(self):
        """保存文档元数据"""
        try:
            with open(self.metadata_file, 'w', encoding='utf-8') as f:
                json.dump(self.documents_metadata, f, ensure_ascii=False, indent=2)
        except Exception as e:
            await self.emit_error("metadata_save", e)
            raise
    
    async def store_document(self, content: str, metadata: Dict[str, Any] = None) -> str:
        """存储文档"""
        try:
            # 生成文档ID
            doc_id = str(uuid.uuid4())
            
            # 创建文档文件路径
            doc_file = self.storage_path / f"{doc_id}.txt"
            
            # 保存文档内容
            with open(doc_file, 'w', encoding='utf-8') as f:
                f.write(content)
            
            # 更新元数据
            self.documents_metadata[doc_id] = {
                "id": doc_id,
                "file_path": str(doc_file),
                "metadata": metadata or {},
                "created_at": datetime.now().isoformat(),
                "size": len(content)
            }
            
            # 保存元数据
            await self._save_metadata()
            
            await self.emit("document_stored", {
                "doc_id": doc_id,
                "size": len(content)
            })
            
            return doc_id
            
        except Exception as e:
            await self.emit_error("document_store", e)
            raise
    
    async def get_document(self, doc_id: str) -> Optional[Document]:
        """获取文档"""
        try:
            if doc_id not in self.documents_metadata:
                return None
            
            doc_meta = self.documents_metadata[doc_id]
            file_path = Path(doc_meta["file_path"])
            
            if not file_path.exists():
                return None
            
            # 读取文档内容
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            return Document(
                id=doc_id,
                content=content,
                metadata=doc_meta["metadata"]
            )
            
        except Exception as e:
            await self.emit_error("document_retrieve", e)
            return None
    
    async def delete_document(self, doc_id: str) -> bool:
        """删除文档"""
        try:
            if doc_id not in self.documents_metadata:
                return False
            
            doc_meta = self.documents_metadata[doc_id]
            file_path = Path(doc_meta["file_path"])
            
            # 删除文件
            if file_path.exists():
                file_path.unlink()
            
            # 删除元数据
            del self.documents_metadata[doc_id]
            await self._save_metadata()
            
            await self.emit("document_deleted", {"doc_id": doc_id})
            return True
            
        except Exception as e:
            await self.emit_error("document_delete", e)
            return False
    
    async def list_documents(self, filter_metadata: Optional[Dict[str, Any]] = None) -> List[str]:
        """列出文档ID"""
        try:
            if not filter_metadata:
                return list(self.documents_metadata.keys())
            
            # 根据元数据过滤
            filtered_docs = []
            for doc_id, doc_meta in self.documents_metadata.items():
                doc_metadata = doc_meta.get("metadata", {})
                if self._matches_filter(doc_metadata, filter_metadata):
                    filtered_docs.append(doc_id)
            
            return filtered_docs
            
        except Exception as e:
            await self.emit_error("document_list", e)
            return []
    
    def _matches_filter(self, doc_metadata: Dict[str, Any], filter_metadata: Dict[str, Any]) -> bool:
        """检查文档元数据是否匹配过滤条件"""
        for key, value in filter_metadata.items():
            if key not in doc_metadata or doc_metadata[key] != value:
                return False
        return True
    
    async def retrieve_document(self, doc_id: str) -> Optional[Document]:
        """检索文档（接口要求的方法名）"""
        return await self.get_document(doc_id)
    
    async def get_storage_stats(self) -> Dict[str, Any]:
        """获取存储统计信息"""
        total_docs = len(self.documents_metadata)
        total_size = sum(meta.get("size", 0) for meta in self.documents_metadata.values())
        
        return {
            "total_documents": total_docs,
            "total_size_bytes": total_size,
            "storage_path": str(self.storage_path)
        }